package com.basker.pisces.core.utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.lang.Nullable;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.basker.pisces.utils.DateUtils;
import com.basker.pisces.utils.EnumUtils;
import com.basker.pisces.utils.NumberUtils;

public class ConvertUtils {

    private static volatile ConvertUtilsBean CONVERT_BEAN;

    /**
     * 尝试将source对象转换为targetType类型的对象
     *
     * @param source
     * @param targetType
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static <T> T convert(@Nullable Object source, Class<T> targetType) {
        if (source == null || targetType == null) {
            return null;
        }

        if (source.getClass().equals(targetType)) {
            return (T) source;
        }

        if (targetType.equals(String.class)) {
            if (source instanceof Collection<?>) {
                return (T) JSON.toJSONString(source);
            } else {
                return (T) Objects.toString(source, null);
            }
        }

        if (NumberUtils.isNumberClass(targetType)) {
            return (T) NumberUtils.parse(source, (Class<? extends Number>) targetType);
        }

        if (targetType.equals(Date.class)) {
            return (T) DateUtils.parse(source);
        }

        if (targetType.equals(Boolean.class) || targetType.equals(boolean.class)) {
            return (T) BooleanUtils.toBooleanObject(Objects.toString(source, null));
        }

        if (targetType.isEnum()) {
            if (source instanceof Number) {
                return (T) EnumUtils.parse((Class<? extends Enum>) targetType, ((Number) source).intValue());
            } else {
                return (T) EnumUtils.parse((Class<? extends Enum>) targetType, source.toString());
            }
        }

        if (source instanceof String && Collection.class.isAssignableFrom(targetType)) {
            return (T) convertList(source.toString());
        }

        Object converted = getConvertUtilsBean().convert(source, targetType);

        return (T) converted;
    }

    /**
     * 转换数组对象
     *
     * <p>
     * [a,b,c]或者a,b,c可以转换为数组；List转换为数组；如果都不是 ，会返回一个数组包装对象
     *
     * @param value
     * @return
     */
    public static Object[] convert2Array(Object value) {
        if (value == null) {
            return ArrayUtils.EMPTY_OBJECT_ARRAY;
        }

        if (value.getClass().isArray()) {
            return (Object[]) value;
        }

        if (value instanceof String) {
            return ((String) value).split(",");
        }

        if (value instanceof Collection<?>) {
            return ((Collection<?>) value).toArray();
        }

        return new Object[]{value};
    }

    public static ConvertUtilsBean getInstance() {
        return CONVERT_BEAN;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static <T> List<T> convertList(String val) {
        if (val.length() == 0 || val.equals("[]")) {
            return new ArrayList<>();
        }

        return new ArrayList(JSONArray.parseArray(val));
    }

    private static ConvertUtilsBean getConvertUtilsBean() {
        if (CONVERT_BEAN == null) {
            synchronized (ConvertUtils.class) {
                if (CONVERT_BEAN == null) {
                    CONVERT_BEAN = BeanUtilsBean.getInstance().getConvertUtils();
                }
            }
        }

        return CONVERT_BEAN;
    }
}
